﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace ITAP.Core.Modelling.Primitives
{
    [Serializable]
    public class CompositePrimitive : IEndedPrimitive
    {
        private List<IPrimitive> innerPrimitives;

        public CompositePrimitive()
        {
            this.innerPrimitives = new List<IPrimitive>();          
        }

        #region IEndedPrimitive Members

        public ModelPoint StartPoint
        {
            get
            {
                return (innerPrimitives[0] as IEndedPrimitive).StartPoint;
            }
            set
            {
            }
        }

        public ModelPoint EndPoint
        {
            get
            {
                return (innerPrimitives[innerPrimitives.Count - 1] as IEndedPrimitive).EndPoint;
            }
            set
            {
            }
        }

        public void MoveStartPoint(ModelPoint destination)
        {
            (this.innerPrimitives[0] as IEndedPrimitive).MoveStartPoint(destination);
        }

        public void MoveEndPoint(ModelPoint destination)
        {
            (this.innerPrimitives[this.innerPrimitives.Count - 1] as IEndedPrimitive).MoveEndPoint(destination);
        }

        public void SetLength(EndedPrimitivePoints basePoint, double length)
        {
        }

        public double GetDistanceFromSegmentToPoint(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] GetProjectionPoints(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public ModelPoint GetProjectionPoint(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectMainLines(IEndedPrimitive primitive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
            //    return primitive.IntersectMainLinesPassive(this, endForSortPoints);
        }

        public ModelPoint[] IntersectMainLines(Line line, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectMainLines(Circle circle, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectMainLinesPassive(Line line, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectMainLinesPassive(Circle circle, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public bool IsPointInSegment(ModelPoint point, bool considerEnds)
        {
            throw new NotImplementedException();
        }

        public double Height
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public IEndedPrimitive ExchangeEnds()
        {
            throw new NotImplementedException();
        }

        public IEndedPrimitive[] BreakToPieces(int numberOfPieces, double gapBetweenPieces)
        {
            throw new NotImplementedException();
        }

        public IEndedPrimitive[] BreakInPoint(ModelPoint point, double gapBetweenPieces)
        {
            throw new NotImplementedException();
        }

        public double GetPathLengthFromProjectionToStart(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IPrimitive Members

        public RectangleF BoundingBox
        {
            get 
            {
                int counter = 0;
                RectangleF bbox = RectangleF.Empty;
                foreach (IPrimitive innerPrimitive in this.innerPrimitives)
                {
                    if (counter == 0)
                    {
                        bbox = innerPrimitive.BoundingBox;
                        counter++;
                        continue;
                    }
                    bbox = RectangleF.Union(bbox, innerPrimitive.BoundingBox);
                    counter++;
                }
                return bbox;
            }
        }

        public void MoveWithOffset(ModelVector offset)
        {
            foreach (IPrimitive primitive in innerPrimitives)
                primitive.MoveWithOffset(offset);
        }

        public ModelPoint GetPoint(double offset)
        {
            throw new NotImplementedException();
        }

        public ModelVector GetTangent(double offset)
        {
            throw new NotImplementedException();
        }

        public ModelVector GetNormalLine(double offset)
        {
            throw new NotImplementedException();
        }

        public double Length
        {
            get 
            {
                double length = 0;
                foreach (IPrimitive primitive in this.innerPrimitives)
                    length += primitive.Length;
                return length;
            }
        }

        public List<IPrimitive> GetContourPrimitives()
        {
            throw new NotImplementedException();
        }

        public List<IPrimitive> InnerPrimitives
        {
            get { return innerPrimitives; }
        }

        public List<IPrimitive> AllInnerPrimitives
        {
            get { throw new NotImplementedException(); }
        }

        public ModelPoint[] Intersect(IPrimitive primitive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] Intersect(Line line, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] Intersect(Circle circle, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] Intersect(LinePrimitive linePrimitive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] Intersect(CirclePrimitive circlePrimitive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] Intersect(Polygon polygon, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectPassive(Line line, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectPassive(LinePrimitive linePritimive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectPassive(Circle circle, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectPassive(CirclePrimitive circlePrimitive, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public ModelPoint[] IntersectPassive(Polygon polygon, EndType endForSortPoints)
        {
            throw new NotImplementedException();
        }

        public bool IsInTolerance(ModelPoint point, double tolerance)
        {
            throw new NotImplementedException();
        }

        public IPrimitive CloneWithOffset(ModelVector offset)
        {
            throw new NotImplementedException();
        }

        public IPrimitive GetOffsetPrimitive(double offset)
        {
            List<IPrimitive> offsetPrimitives = new List<IPrimitive>();
            foreach(IPrimitive innerPrimitive in this.InnerPrimitives)
                offsetPrimitives.Add(innerPrimitive.GetOffsetPrimitive(offset));

           return PrimitiveFactory.CreateCompositePrimitive(offsetPrimitives);
        }

        public void Rotate(ModelPoint rotateCenter, double angle)
        {
            foreach (IPrimitive innerPrimitive in this.InnerPrimitives)
                innerPrimitive.Rotate(rotateCenter, angle);
        }

        private string name;
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public bool Validate()
        {
            throw new NotImplementedException();
        }

        public void Update()
        {
            foreach (IPrimitive innerPrimitive in this.innerPrimitives)
                innerPrimitive.Update();
        }

        public double GetDistanceToPoint(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public ModelPoint GetNearestPrimitivePoint(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public bool IsPointInsidePrimitive(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        public void AcceptVisitor(IPrimitiveVisitor visitor)
        {
            visitor.Visit(this);
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
            List<IPrimitive> clonedPrimitives = new List<IPrimitive>();
            foreach (IPrimitive innerPrimitive in this.innerPrimitives)
                clonedPrimitives.Add(innerPrimitive.Clone() as IPrimitive);
            return PrimitiveFactory.CreateCompositePrimitive(clonedPrimitives);
        }

        #endregion

        #region IEquatable<IPrimitive> Members

        public bool Equals(IPrimitive other)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEndedPrimitive Members


        public bool IsPointOnPrimitive(ModelPoint point)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
